package hehe.validation.annotation;

import hehe.validation.util.ValidatorUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * 类注解
 *<B>说明：</B>
 *<pre>
 * 略
 *</pre>
 *<B>示例：</B>
 *<pre>
 *  略
 *</pre>
 *<B>日志：</B>
 *<pre>
 *  略
 *</pre>
 *<B>注意事项：</B>
 *<pre>
 *  略
 *</pre>
 */
public class AnnotationMetadata
{
    protected final static String FIELD_ANNOTATION_NAME = "field";

    /**
     * 目标类
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected Class targetClazz;

    public AnnotationMetadata(Class targetClazz)
    {
        this.targetClazz = targetClazz;
    }

    /**
     * 解析类字段注解
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public void parseFieldAnnotation(List<Class> annotationList) throws Exception
    {
        // 获取类的所有属性
        Map<String,Field> attrs = ValidatorUtil.getFields(this.targetClazz);
        Field field;
        Annotation[] annotations;
        Method annMethod;

        // 遍历属性,获取注解
        for (Map.Entry<String,Field> attrsEntry : attrs.entrySet()) {
            field = attrsEntry.getValue();
            annotations =  field.getDeclaredAnnotations();
            if (annotations.length == 0) {
                continue;
            }

            for (Annotation ann:annotations) {
                Class annClazz = ann.annotationType();
                if (annotationList.contains(annClazz)) {
                    // 查找验证器注解处理器
                    Class annotationProcessor = this.getAnnotationProcessor(ann);
                    if (annotationProcessor != null) {
                        annMethod = annotationProcessor.getMethod(FIELD_ANNOTATION_NAME, Class.class,Field.class,Annotation.class);
                        annMethod.invoke(annotationProcessor.newInstance(),this.targetClazz,field,ann);
                    }
                }
            }
        }
    }

    /**
     * 获取注解的处理器
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public Class<?> getAnnotationProcessor(Annotation annotation)
    {
        Constraint constraint = annotation.annotationType().getAnnotation(Constraint.class);
        if (constraint != null) {
            return constraint.processor();
        }

        return null;
    }

}
